package com.coffee.wx.service.impl;

import cn.hutool.core.lang.Console;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.XmlUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.coffee.wx.entity.messages.ReplyImageMessage;
import com.coffee.wx.entity.messages.ReplyTextMessage;
import com.coffee.wx.enums.EventTypeEnum;
import com.coffee.wx.enums.MsgTypeEnum;
import com.coffee.wx.service.IActivityService;
import com.coffee.wx.service.IWxService;
import com.coffee.wx.uitls.BaiDuAiUtils;
import com.coffee.wx.uitls.ConstellationUtils;
import com.coffee.wx.uitls.TokenUtils;
import com.coffee.wx.uitls.TypeChangeUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Service;
import org.w3c.dom.Document;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

@Service
public class WxServiceImpl implements IWxService {

    public static final String TOKEN = "coffee";

    public static final String ACTIVITY_KEY = "activity:";

    @Resource
    private IActivityService activityService;

    @Override
    public String buildResponse(Map<String, Object> xml) {
        String msgType = MapUtil.getStr(xml, "MsgType");
        String toUserName = MapUtil.getStr(xml, "ToUserName");
        String fromUserName = MapUtil.getStr(xml, "FromUserName");
        String msgContent = null, msgMediaId = null;
        String returnMsgType = MsgTypeEnum.TEXT.getValue();

        if (MsgTypeEnum.EVENT.getValue().equals(msgType)) { // 事件
            String event = MapUtil.getStr(xml, "Event");
            String eventKey = MapUtil.getStr(xml, "EventKey");
            if (EventTypeEnum.SUBSCRIBE.getValue().equals(event)) {

                msgContent = "欢迎关注 我们正在举办集赞领礼品活动，您可以" + activityService.signUp();

            } else if (EventTypeEnum.UNSUBSCRIBE.getValue().equals(event)) {
                msgContent = "欢迎下次关注";
            } else if (EventTypeEnum.CLICK.getValue().equals(event)) {
                msgContent = "key = " + eventKey + " 志当存高远。";
            } else if (EventTypeEnum.PIC_PHOTO_OR_ALBUM.getValue().equals(event)) {
                msgContent = "点击了图片识别文字按钮";
            } else if (EventTypeEnum.SCAN.getValue().equals(event)) {
                if (eventKey.contains(ACTIVITY_KEY)) { // 扫码助力
                    String toOpenId = eventKey.substring(eventKey.indexOf(ACTIVITY_KEY) + ACTIVITY_KEY.length());
                    if(ObjectUtil.notEqual(toOpenId, fromUserName)){
                        msgContent = activityService.scanCodeAssistance(toOpenId, fromUserName);
                    } else {
                        msgContent = "不能助力自己";
                    }
                } else {
                    msgContent = "扫描二维码";
                }
            } else {
                msgContent = "未识别到事件";
            }
        } else if (MsgTypeEnum.TEXT.getValue().equals(msgType)) { // 文本
            String content = MapUtil.getStr(xml, "Content");
            // 判断content是否是星座
            if (content.contains("座")) {
                msgContent = ConstellationUtils.getConstellation(content);
            } else if ("海报".equals(content)) {
                returnMsgType = MsgTypeEnum.IMAGE.getValue();
                msgMediaId = activityService.getPoster(fromUserName);
            } else {
                msgContent = switch (content) {
                    case "图文" -> "收到图片";
                    case "token" -> TokenUtils.getToken();
                    case "报名" -> activityService.signUp();
                    case "排行榜" -> activityService.getRankingList();
                    default -> "自行束修以上，吾未尝无诲焉。";
                };
            }

        } else if (MsgTypeEnum.IMAGE.getValue().equals(msgType)) {

            String picUrl = MapUtil.getStr(xml, "PicUrl");
            msgContent = BaiDuAiUtils.textRecognition(picUrl);

        } else {
            msgContent = "识别失败，发送默认信息";
        }


        if (MsgTypeEnum.TEXT.getValue().equals(returnMsgType)) {

            return TypeChangeUtils.beanToXmlStr(new ReplyTextMessage()
                    .setToUserName(fromUserName)
                    .setFromUserName(toUserName)
                    .setCreateTime(System.currentTimeMillis())
                    .setMsgType(returnMsgType)
                    .setContent(msgContent));

        } else if (MsgTypeEnum.IMAGE.getValue().equals(returnMsgType)) {
            Map<String, Object> imageMap = new HashMap<>();
            imageMap.put("MediaId", msgMediaId);

            return TypeChangeUtils.beanToXmlStr(new ReplyImageMessage()
                    .setToUserName(fromUserName)
                    .setFromUserName(toUserName)
                    .setCreateTime(System.currentTimeMillis())
                    .setMsgType(returnMsgType)
                    .setImage(imageMap));
        } else {
            return null;
        }
    }

    @Override
    public String bindCheck(String signature, String timestamp, String nonce, String echostr) {
        System.out.println("signature = " + signature);
        System.out.println("timestamp = " + timestamp);
        System.out.println("nonce = " + nonce);
        System.out.println("echostr = " + echostr);

        String[] tempArrays = {TOKEN, timestamp, nonce};
        Arrays.sort(tempArrays);
        return DigestUtil.sha1Hex(String.join("", tempArrays));
    }

    /**
     * 读取请求体中的信息
     *
     * @param request
     * @return
     */
    @Override
    public Map<String, Object> readRequestBody(HttpServletRequest request) {

        String body = TypeChangeUtils.requestToMap(request);

        Document document = XmlUtil.parseXml(body);
        Map<String, Object> bodyMap = XmlUtil.xmlToMap(document);
        Map<String, Object> xml = MapUtil.getQuietly(bodyMap, "xml", Map.class, null);
        Console.log(" 推送的消息 ====> " + xml);

        if (xml != null) {

            String msgType = MapUtil.getStr(xml, "MsgType");

            if (MsgTypeEnum.TEXT.getValue().equals(msgType)) {

                Console.log(" 文本内容 ====> " + MapUtil.getStr(xml, "Content"));

            } else if (MsgTypeEnum.IMAGE.getValue().equals(msgType)) {

                Console.log(" 图片地址 ====> " + MapUtil.getStr(xml, "PicUrl"));

            } else if (MsgTypeEnum.VOICE.getValue().equals(msgType)) {

                Console.log(" 语音格式 ====> " + MapUtil.getStr(xml, "Format"));

                Console.log(" 语音消息媒体id ====> " + MapUtil.getStr(xml, "MediaId"));

            } else if (MsgTypeEnum.VIDEO.getValue().equals(msgType)) {

                Console.log(" 视频消息缩略图的媒体id ====> " + MapUtil.getStr(xml, "ThumbMediaId"));

            } else if (MsgTypeEnum.SHORTVIDEO.getValue().equals(msgType)) {

                Console.log(" 小视频消息缩略图的媒体id ====> " + MapUtil.getStr(xml, "ThumbMediaId"));

            } else if (MsgTypeEnum.LOCATION.getValue().equals(msgType)) {

                Console.log(" 地理位置信息 ====> " + MapUtil.getStr(xml, "Label"));

            } else if (MsgTypeEnum.LINK.getValue().equals(msgType)) {

                Console.log(" 消息标题 ====> " + MapUtil.getStr(xml, "Title"));

            } else if (MsgTypeEnum.EVENT.getValue().equals(msgType)) {
                String event = MapUtil.getStr(xml, "Event");
                if (EventTypeEnum.SUBSCRIBE.getValue().equals(event)) {

                    String eventKey = MapUtil.getStr(xml, "EventKey");
                    if (eventKey.startsWith("qrscene_")) {

                        Console.log(" 扫描二维码后关注事件 ====> " + eventKey.substring("qrscene_".length()));

                    } else {
                        Console.log(" 关注事件 ====> " + event);
                    }

                } else if (EventTypeEnum.UNSUBSCRIBE.getValue().equals(event)) {

                    Console.log(" 取消关注事件 ====> " + event);

                } else if (EventTypeEnum.CLICK.getValue().equals(event)) {

                    Console.log(" 点击菜单拉取消息事件 ====> " + event);

                } else if (EventTypeEnum.SCAN.getValue().equals(event)) {

                    Console.log(" 扫描二维码事件 ====> " + event);

                } else {
                    Console.log(" 其他事件 ====> " + event);
                }
            } else {
                Console.log(" 其他消息类型 ====> " + msgType);
            }
        }
        return xml;
    }

}
